﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Nui.Vision;

namespace kinect_music_shooter.GameWorld
{
    public class Avatar
    {
        #region Fields

        //flags
        public bool isTracked = false;

        //knotes
        public GameObject Head;
        GameObject Neck;
        GameObject LeftShoulder;
        GameObject LeftElbow;
        public GameObject LeftHand;
        GameObject RightShoulder;
        GameObject RightElbow;
        public GameObject RightHand;
        public GameObject Torso;
        GameObject LeftHip;
        GameObject LeftKnee;
        GameObject LeftFoot;
        GameObject RightHip;
        GameObject RightKnee;
        GameObject RightFoot;

        //Bones
        BodyPart bNeck;
        BodyPart bChest;
        BodyPart bRightCollar;
        BodyPart bLeftCollar;
        BodyPart bLeftShoulder;
        BodyPart bLeftForearm;
        BodyPart bRightShoulder;
        BodyPart bRightForearm;
        BodyPart bLeftHip;
        BodyPart bLeftShin;
        BodyPart bLeftThigh;
        BodyPart bRightHip;
        BodyPart bRightShin;
        BodyPart bRightThigh;

        BodyPart bTorso;

        Texture2D pixel_tex;
        float width = 0;
        float height = 0;

        Vector3 OldRightHand = Vector3.Zero;
        Vector3 OldLeftHand = Vector3.Zero;

        Vector3 WurfStart;
        Vector3 WurfEnd;
        Vector3 WurfStartLeft;
        Vector3 WurfEndLeft;
        bool WurfNullright;
        bool WurfNullleft;
        //Vector3 Head = Vector3.Zero;
        //Vector3 Neck = Vector3.Zero;
        /* Vector3 LeftShoulder.X, firstuser.LeftShoulder.Y), Color.DarkBlue);
        Vector3 LeftElbow.X, firstuser.LeftElbow.Y), Color.DarkBlue);
        Vector3 LeftHand.X, firstuser.LeftHand.Y), Color.DarkBlue);
        Vector2 RightShoulder.X, firstuser.RightShoulder.Y), Color.DarkBlue);
        Vector2 RightElbow.X, firstuser.RightElbow.Y), Color.DarkBlue);
        Vector2 RightHand.X, firstuser.RightHand.Y), Color.DarkBlue);
        Vector2 Torso.X, firstuser.Torso.Y), Color.DarkBlue);
        Vector2 LeftHip.X, firstuser.LeftHip.Y), Color.DarkBlue);
        Vector2 LeftKnee.X, firstuser.LeftKnee.Y), Color.DarkBlue);
        Vector2 LeftFoot.X, firstuser.LeftFoot.Y), Color.DarkBlue);
        Vector2 RightHip.X, firstuser.RightHip.Y), Color.DarkBlue);
        Vector2 RightKnee.X, firstuser.RightKnee.Y), Color.DarkBlue);
        Vector2 RightFoot.*/

        #endregion

        public Avatar(GraphicsDevice pGraphicsDevice)
        {
            Head = new GameObject();
            Neck = new GameObject();
            LeftShoulder = new GameObject();
            LeftElbow = new GameObject();
            LeftHand = new GameObject();
            RightShoulder = new GameObject();
            RightElbow = new GameObject();
            RightHand = new GameObject();
            Torso = new GameObject();
            LeftHip = new GameObject();
            LeftKnee = new GameObject();
            LeftFoot = new GameObject();
            RightHip = new GameObject();
            RightKnee = new GameObject();
            RightFoot = new GameObject();

            bNeck = new BodyPart( pGraphicsDevice);
            bChest = new BodyPart( pGraphicsDevice);
            bRightCollar = new BodyPart(pGraphicsDevice);
            bLeftCollar = new BodyPart(pGraphicsDevice);
            bLeftShoulder = new BodyPart(pGraphicsDevice);
            bLeftForearm = new BodyPart(pGraphicsDevice);
            bRightShoulder = new BodyPart(pGraphicsDevice);
            bRightForearm = new BodyPart(pGraphicsDevice);
            bLeftHip = new BodyPart(pGraphicsDevice);
            bLeftShin = new BodyPart(pGraphicsDevice);
            bLeftThigh = new BodyPart(pGraphicsDevice);
            bRightHip = new BodyPart(pGraphicsDevice);
            bRightShin = new BodyPart(pGraphicsDevice);
            bRightThigh = new BodyPart(pGraphicsDevice);

            bTorso = new BodyPart();

            Vector3 tStartPosition = new Vector3(0, 0, -0.0f);
            Head.position = new Vector3(0,10,40);
            Neck.position = new Vector3(0, 0, 40);
            LeftShoulder.position = tStartPosition;
            LeftElbow.position = tStartPosition;
            LeftHand.position = tStartPosition;
            RightShoulder.position = tStartPosition;
            RightElbow.position = tStartPosition;
            RightHand.position = tStartPosition;
            Torso.position = tStartPosition;
            LeftHip.position = tStartPosition;
            LeftKnee.position = tStartPosition;
            LeftFoot.position = tStartPosition;
            RightHip.position = tStartPosition;
            RightKnee.position = tStartPosition;
            RightFoot.position = tStartPosition;

            bNeck.init(Neck, Head, 0.5f);
            bChest.init(Torso, Neck, 0.5f);
            bRightCollar.init(Neck, RightShoulder, 0.5f);
            bLeftCollar.init(Neck, LeftShoulder, 0.5f);
            bLeftShoulder.init(LeftShoulder, LeftElbow, 0.5f);
            bLeftForearm.init(LeftElbow, LeftHand, 0.5f);
            bRightShoulder.init(RightShoulder, RightElbow, 0.5f);
            bRightForearm.init(RightElbow, RightHand, 0.5f);
            bLeftHip.init(Torso, LeftHip, 0.5f);
            bLeftShin.init(LeftKnee, LeftFoot, 0.5f);
            bLeftThigh.init(LeftHip, LeftKnee, 0.5f);
            bRightHip.init(Torso, RightHip, 0.5f);
            bRightShin.init(RightKnee, RightFoot, 0.5f);
            bRightThigh.init(RightHip, RightKnee, 0.5f);
            //bTorso
        }

        public void loadModel(GraphicsDevice graphicsDevice, Model pModel)
        {
            Head.loadModel(pModel);
            Neck.loadModel(pModel);
            LeftShoulder.loadModel(pModel);
            LeftElbow.loadModel(pModel);
            LeftHand.loadModel(pModel);
            RightShoulder.loadModel(pModel);
            RightElbow.loadModel(pModel);
            RightHand.loadModel(pModel);
            Torso.loadModel(pModel);
            LeftHip.loadModel(pModel);
            LeftKnee.loadModel(pModel);
            LeftFoot.loadModel(pModel);
            RightHip.loadModel(pModel);
            RightKnee.loadModel(pModel);
            RightFoot.loadModel(pModel);

        }

        public void LoadTexture(Texture2D texture){
            //bNeck.LoadTexture(texture);
        }

        public void Update()
        {
            /*
            Head;
            Neck;
            LeftShoulder;
             LeftElbow;
             LeftHand;
             RightShoulder;
             RightElbow;
             RightHand;
             Torso;
             LeftHip;
             LeftKnee;
             LeftFoot;
             RightHip;
             RightKnee;
             RightFoot;*/
        }

        private void initUser(NuiUser firstuser)
        {
            width = -(float)firstuser.Head.X;
            height = -(float)firstuser.Head.Y;

            initParts(firstuser.Head.X, firstuser.Head.Y, firstuser.Head.Z, Head);
            initParts(firstuser.Neck.X, firstuser.Neck.Y, firstuser.Neck.Z, Neck);
            initParts(firstuser.LeftShoulder.X, firstuser.LeftShoulder.Y, firstuser.LeftShoulder.Z, LeftShoulder);
            initParts(firstuser.LeftElbow.X, firstuser.LeftElbow.Y, firstuser.LeftElbow.Z, LeftElbow);
            initParts(firstuser.LeftHand.X, firstuser.LeftHand.Y, firstuser.LeftHand.Z, LeftHand);
            initParts(firstuser.RightShoulder.X, firstuser.RightShoulder.Y, firstuser.RightShoulder.Z, RightShoulder);

            initParts(firstuser.RightElbow.X, firstuser.RightElbow.Y, firstuser.RightElbow.Z, RightElbow);
            initParts(firstuser.RightHand.X, firstuser.RightHand.Y, firstuser.RightHand.Z, RightHand);
            initParts(firstuser.Torso.X, firstuser.Torso.Y, firstuser.Torso.Z, Torso);
            initParts(firstuser.LeftHip.X, firstuser.LeftHip.Y, firstuser.LeftHip.Z, LeftHip);
            initParts(firstuser.LeftKnee.X, firstuser.LeftKnee.Y, firstuser.LeftKnee.Z, LeftKnee);
            initParts(firstuser.LeftFoot.X, firstuser.LeftFoot.Y, firstuser.LeftFoot.Z, LeftFoot);
            initParts(firstuser.RightHip.X, firstuser.RightHip.Y, firstuser.RightHip.Z, RightHip);
            initParts(firstuser.RightKnee.X, firstuser.RightKnee.Y, firstuser.RightKnee.Z, RightKnee);
            initParts(firstuser.RightFoot.X, firstuser.RightFoot.Y, firstuser.RightFoot.Z, RightFoot);

            isTracked = true;
        }

        public void updatetUser(NuiUser firstuser)
        {

            if (isTracked == true)
            {
                initUser(firstuser);
            }
            else
            {
                if (width == 0 && height == 0)
                {
                    width = -(float)firstuser.Head.X;
                    height = -(float)firstuser.Head.Y;
                }

                OldRightHand.Z = RightHand.position.Z;
                OldRightHand.Y = RightHand.position.Y;
                OldRightHand.X = RightHand.position.X;

                OldLeftHand.Z = LeftHand.position.Z; //2.Hand Z
                OldLeftHand.Y = LeftHand.position.Y; //2.Hand Y
                OldLeftHand.X = LeftHand.position.X; //2.Hand X

                //Wichtig: die Reihnfolge, da die bodyparts voneinander abhängen
                initParts(firstuser.Torso.X, firstuser.Torso.Y, firstuser.Torso.Z, Torso);

                /*updateParts(firstuser.Head.X, firstuser.Head.Y, firstuser.Head.Z, Head);
                updateParts(firstuser.Neck.X, firstuser.Neck.Y, firstuser.Neck.Z, Neck);
                updateParts(firstuser.LeftShoulder.X, firstuser.LeftShoulder.Y, firstuser.LeftShoulder.Z, LeftShoulder);
                updateParts(firstuser.LeftElbow.X, firstuser.LeftElbow.Y, firstuser.LeftElbow.Z, LeftElbow);
                updateParts(firstuser.LeftHand.X, firstuser.LeftHand.Y, firstuser.LeftHand.Z, LeftHand);
                updateParts(firstuser.RightShoulder.X, firstuser.RightShoulder.Y, firstuser.RightShoulder.Z, RightShoulder);

                updateParts(firstuser.RightElbow.X, firstuser.RightElbow.Y, firstuser.RightElbow.Z, RightElbow);
                updateParts(firstuser.RightHand.X, firstuser.RightHand.Y, firstuser.RightHand.Z, RightHand);

                updateParts(firstuser.LeftHip.X, firstuser.LeftHip.Y, firstuser.LeftHip.Z, LeftHip);
                updateParts(firstuser.LeftKnee.X, firstuser.LeftKnee.Y, firstuser.LeftKnee.Z, LeftKnee);
                updateParts(firstuser.LeftFoot.X, firstuser.LeftFoot.Y, firstuser.LeftFoot.Z, LeftFoot);
                updateParts(firstuser.RightHip.X, firstuser.RightHip.Y, firstuser.RightHip.Z, RightHip);
                updateParts(firstuser.RightKnee.X, firstuser.RightKnee.Y, firstuser.RightKnee.Z, RightKnee);
                updateParts(firstuser.RightFoot.X, firstuser.RightFoot.Y, firstuser.RightFoot.Z, RightFoot);*/
            }
        }

        public bool wurf()
        {

            if ((RightHand.position - OldRightHand).Z >= 0.3f && (RightHand.position - OldRightHand).Length() >= 0.7f)
            {
                if (WurfNullright == true)
                {
                    WurfEnd = RightHand.position;
                }
                else
                {
                    WurfStart = RightHand.position;
                    WurfNullright = true;
                }
            }
            else if (WurfNullright == true)
            {
                return true;
            }
            return false;
        }

        public bool wurfzwei()
        {
            if ((LeftHand.position - OldLeftHand).Z >= 0.3f && (LeftHand.position - OldLeftHand).Length() >= 0.7f)
            {
                if (WurfNullleft == true)
                {
                    WurfEndLeft = LeftHand.position;

                }
                else
                {
                    WurfStartLeft = LeftHand.position;
                    WurfNullleft = true;
                }

            }
            else if (WurfNullleft == true)
            {
                return true;
            }
            return false;
        }

        public bool hadoken()
        {
            if ((LeftHand.position.X - RightHand.position.X > -0.3f) && (LeftHand.position.X - RightHand.position.X < 0.3f))
            {
                /*if ((LeftHand.position.Y - RightHand.position.Y > -0.3f) && (LeftHand.position.Y - RightHand.position.Y < 0.3f))
                {
                    if ((LeftHand.position.Z - RightHand.position.Z > -0.3f) && (LeftHand.position.Z - RightHand.position.Z < 0.3f))
                    {
                        return true;
                    }
                }*/
                return true;
            }

            return false;
        }

        public Vector3 getWurfVector()
        {
            WurfNullright = false;
            return (WurfEnd - WurfStart);

        }

        public Vector3 getWurfVectorLeft()
        {
            WurfNullleft = false;
            return (WurfEndLeft - WurfStartLeft);
        }

        private void initParts(float x, float y, float z, GameObject Part)
        {
            Part.position.X = x + width;
            Part.position.Y = y + height;
            Part.position.Z = z;

            Part.position.Z *= -0.01f;
            Part.position.Z += 40.0f;
            Part.position.X /= -Part.position.Z;
            Part.position.Y /= -Part.position.Z;
        }

        private void updateParts(float x, float y, float z, GameObject Part, GameObject Base, BodyPart bp)
        {
            Vector3 Position = Vector3.Zero;

            Position.X = x + width;
            Position.Y = y + height;
            Position.Z = z;

            Position.Z *= -0.01f;
            Position.Z += 40.0f;
            Position.X /= -Part.position.Z;
            Position.Y /= -Part.position.Z;
            Position = (Base.position - Position);
            Position.Normalize();
            Position *= bp.height;

            Part.position = Base.position + Position;
        }

        public void Draw(GraphicsDevice graphicsDevice, Camera camera)
        {
            Head.Draw(graphicsDevice, camera);
            Neck.Draw(graphicsDevice, camera);
            LeftShoulder.Draw(graphicsDevice, camera);
            LeftElbow.Draw(graphicsDevice, camera);
            LeftHand.Draw(graphicsDevice, camera);
            RightShoulder.Draw(graphicsDevice, camera);
            RightElbow.Draw(graphicsDevice, camera);
            RightHand.Draw(graphicsDevice, camera);
            Torso.Draw(graphicsDevice, camera);
            LeftHip.Draw(graphicsDevice, camera);
            LeftKnee.Draw(graphicsDevice, camera);
            LeftFoot.Draw(graphicsDevice, camera);
            RightHip.Draw(graphicsDevice, camera);
            RightKnee.Draw(graphicsDevice, camera);
            RightFoot.Draw(graphicsDevice, camera);

            bNeck.draw(graphicsDevice, camera);
            /*bChest.draw(graphicsDevice, camera);
            bRightCollar.draw(graphicsDevice, camera);
            bLeftCollar.draw(graphicsDevice, camera);
            bLeftShoulder.draw(graphicsDevice, camera);
            bLeftForearm.draw(graphicsDevice, camera);
            bRightShoulder.draw(graphicsDevice, camera);
            bRightForearm.draw(graphicsDevice, camera);
            bLeftHip.draw(graphicsDevice, camera);
            bLeftShin.draw(graphicsDevice, camera);
            bLeftThigh.draw(graphicsDevice, camera);
            bRightHip.draw(graphicsDevice, camera);
            bRightShin.draw(graphicsDevice, camera);
             bRightThigh.draw(graphicsDevice, camera);*/
        }

        public struct BodyPart
        {
            GameObject2D Part;
            public float height;
            float width;

            public BodyPart(GraphicsDevice pGraphicsDevice)
            {
                Part = new GameObject2D(pGraphicsDevice);
                height = 0;
                width = 0;
            }

            public void LoadTexture(Texture2D texture){
                Part.LoadTexture(texture);
            }

            public void init(GameObject G1, GameObject G2, float pwidth)//G1 is the origin
            {
                Vector3 up = G2.position - G1.position;
                Vector3 origin = up / 2 + G1.position;
                height = up.Length();
                width = pwidth;

                Part.init(origin, Vector3.Forward, Vector3.Up, width, height);
                
            }

            public void update(GameObject G1, GameObject G2)//G1 is the origin
            {
                Vector3 up = G2.position - G1.position;
                Vector3 origin = up / 2 + G1.position;
                Part.init(origin, Vector3.Forward, up, width, height);
            }

            public void draw(GraphicsDevice graphicsDevice, Camera camera)
            {
                Part.Draw(graphicsDevice, camera);
            }
        }
    }
}
